package cn.maihe.elg.operation.web.business;

import cn.hutool.core.codec.Base64;
import cn.maihe.elg.operation.config.ElgConfig;
import cn.maihe.elg.operation.config.ZtAccountInfo;
import cn.maihe.elg.operation.exception.ErrorCode;
import cn.maihe.elg.operation.exception.SystemRuntimeException;
import cn.maihe.elg.operation.model.enums.AcceptOrderStatus;
import cn.maihe.elg.operation.model.enums.AttachmentFileType;
import cn.maihe.elg.operation.model.enums.CenterNoEnum;
import cn.maihe.elg.operation.model.enums.GuaranteeCategory;
import cn.maihe.elg.operation.model.vo.bidder.BidderApplyInfo;
import cn.maihe.elg.operation.model.vo.bidder.CustomerPayUrlInfo;
import cn.maihe.elg.operation.model.vo.order.AcceptOrderDetailVO;
import cn.maihe.elg.operation.repository.entity.AcceptOrderInfoDO;
import cn.maihe.elg.operation.repository.entity.BidCustomerDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeAttachmentInfoDO;
import cn.maihe.elg.operation.repository.entity.GuaranteeInstitutionDO;
import cn.maihe.elg.operation.repository.entity.OrganizationDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDO;
import cn.maihe.elg.operation.repository.entity.ProjectInfoDOCondition;
import cn.maihe.elg.operation.repository.entity.ProjectInfoVo;
import cn.maihe.elg.operation.repository.entity.UserDO;
import cn.maihe.elg.operation.repository.entity.entityCustom.UserDOCustom;
import cn.maihe.elg.operation.security.model.UserContext;
import cn.maihe.elg.operation.security.model.token.JwtToken;
import cn.maihe.elg.operation.security.model.token.JwtTokenFactory;
import cn.maihe.elg.operation.service.business.BidCustomerService;
import cn.maihe.elg.operation.service.business.InstitutionService;
import cn.maihe.elg.operation.service.business.ProjectInfoService;
import cn.maihe.elg.operation.service.order.AcceptOrderInfoService;
import cn.maihe.elg.operation.service.order.GuaranteeAttachmentInfoService;
import cn.maihe.elg.operation.service.system.OrganizationService;
import cn.maihe.elg.operation.service.system.UserService;
import cn.maihe.elg.operation.supports.system.ElgResourceService;
import cn.maihe.elg.operation.utils.DateUtil;
import cn.maihe.elg.operation.utils.IdGenerate;
import cn.maihe.framework.starter.base.sql.PageBo;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.File;
import java.nio.file.Path;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @Description 投标者操作入口
 * @Author WJH
 * @Date 2021/03/25
 */
@Api(value = "投标者操作管理", tags = "投标者操作管理")
@RestController
@RequestMapping("/api/bidder")
@Slf4j
public class BidderOperateController {
    @Resource
    private ProjectInfoService projectInfoService;
    @Resource
    private ElgConfig elgConfig;
    @Resource
    private UserService userService;
    @Resource
    private OrganizationService organizationService;
    @Resource
    private InstitutionService institutionService;
    @Resource
    private ElgResourceService elgResourceService;
    @Resource
    private BidCustomerService bidCustomerService;
    @Resource
    private GuaranteeAttachmentInfoService guaranteeAttachmentInfoService;
    @Resource
    private AcceptOrderInfoService acceptOrderInfoService;
    @Resource
    private ZtAccountInfo ztAccountInfo;

    @ApiOperation(value = "分页查询投标者操作", notes = "根据投标项目标段编码、标段名称、投递投标文件截止日 分页查询")
    @RequestMapping(value = "/listCenterProjects", method = RequestMethod.GET)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "pageNo", value = "页数", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "pageSize", value = "每页大小", dataType = "int", paramType = "query", required = true),
            @ApiImplicitParam(name = "sectionCode", value = "标段编码", dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "sectionName", value = "标段名称", dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "bidOpenTimeRange", value = "投递投标文件截止日（startDate,endDate）", dataType = "String", paramType = "query"),
    })
    public PageBo<ProjectInfoDO> pageList(int pageNo, int pageSize, String bidOpenTimeRange, ProjectInfoVo vo) {
        ProjectInfoDOCondition condition = ProjectInfoDOCondition.builder();
        if (StringUtils.isNotBlank(bidOpenTimeRange)) {
            String[] rangeAy = bidOpenTimeRange.split(",");
            if (rangeAy.length > 1) {
                condition.andBidOpenTimeBetween(rangeAy[0] + " 00:00:00", rangeAy[1] + " 23:59:59");
            }
        }
        if (StringUtils.isNotBlank(vo.getSectionCode())) {
            condition.andSectionCodeLike("%" + vo.getSectionCode() + "%s");
        }
        if (StringUtils.isNotBlank(vo.getSectionName())) {
            condition.andSectionNameLike("%" + vo.getSectionName() + "%");
        }

        return projectInfoService.selectPageBo(condition.build(), pageNo, pageSize);
    }


    @Resource
    private JwtTokenFactory tokenFactory;

    @GetMapping("/getToken")
    @Deprecated
    public Map<String, String> getToken4Bidder(@RequestParam("userName") String userName) {
        if (1 == 1) return null;

        UserDOCustom user = userService.getByUsername(userName);

        if (user.getRoleList() == null) {
            throw new InsufficientAuthenticationException("User has no roles assigned");
        }

        List<String> funcResource = userService.getUserPerm(user.getId());
        List<GrantedAuthority> authorities = funcResource.stream()
                .map(SimpleGrantedAuthority::new)
                .collect(Collectors.toList());


        OrganizationDO org = organizationService.getOrganizationByCode(user.getOrgCode());
        Long curOrgId = org == null ? null : org.getId();

        UserContext userContext = UserContext.create(user.getId().toString(), user.getUsername(), authorities,
                user.getOrgCode(), user.getType(), user.getFullName(), user.getName(), curOrgId, null, null, user, user.getOrgId(), null,null);

        JwtToken accessToken = tokenFactory.createAccessJwtToken(userContext);
        JwtToken refreshToken = tokenFactory.createRefreshToken(userContext);

        Map<String, String> tokenMap = new HashMap<String, String>(16);
        tokenMap.put("token", accessToken.getToken());
        tokenMap.put("refreshToken", refreshToken.getToken());
        if (userContext.getOrgId() != null) {
            tokenMap.put("orgId", userContext.getOrgId().toString());
        } else {
            tokenMap.put("orgId", "-1");
        }
        tokenMap.put("orgCode", userContext.getOrgCode());
        tokenMap.put("orgName", userContext.getOrgName());
        tokenMap.put("name", userContext.getName());
        tokenMap.put("userType", userContext.getUserType().toString());
        tokenMap.put("loginCount", (userContext.getUser().getLoginCount() + 1) + "");
        if (userContext.getUser().getPwdExpiredTime().before(new Date())) {
            tokenMap.put("pwdExpire", "1");
        }
        Date date = userContext.getUser().getLastLoginTime();
        if (date != null) {
            tokenMap.put("lastLoginTime", DateUtil.formateDate(date, DateUtil.FORMAT_DATETIME));
        } else {
            tokenMap.put("lastLoginTime", "");
        }


        return tokenMap;
    }


    @GetMapping("/getBidderApply")
    public Object getBidderApply(@RequestParam(value = "projectId", required = false) String projectId, @RequestParam(value = "bidderName", required = false) String bidderName) {
        Assert.hasText(projectId, "项目id值为空");
        Assert.hasText(bidderName, "投标客户值为空");

        ProjectInfoDO projectInfoDO = projectInfoService.selectById(projectId);
        Map<String, Object> objectMap = new HashMap<>(BeanMap.create(projectInfoDO));


        OrganizationDO organizationDO = organizationService.getOrganizationByCode("DXDB");
        objectMap.put("orgName", organizationDO.getFullName());
        objectMap.put("orgContactName", organizationDO.getContactName());
        objectMap.put("orgContactTel", organizationDO.getContactTel());

        UserDO userDO = userService.getByUsername(bidderName);
//        OrganizationDO bidderOrganizationDO = organizationService.getOrganizationByCode(userDO.getOrgCode());

        objectMap.put("bidderOrgName", "健民工程建筑公司");
        objectMap.put("bidderName", bidderName);
        objectMap.put("bidderContactName", userDO.getName());
        objectMap.put("bidderContactTel", userDO.getMobileNo());


        File tenderFile = elgResourceService.getFileByRelativePath("/tmp/建设工程招标文件范本.doc");
        String tenderFileURI = elgResourceService.save2OfdPath(tenderFile.toPath(), "mockBidder001", "招标文件");
        //默认招标文件
        objectMap.put("tenderFile", tenderFileURI);
        objectMap.put("tenderFileName", elgResourceService.getFileNameAndType(tenderFile.toPath()));

        File orgBusinessLicFile = elgResourceService.getFileByRelativePath("/tmp/营业执照模板.jpg");
        String orgBusinessLicFileURI = elgResourceService.save2OfdPath(orgBusinessLicFile.toPath(), "mockBidder001", "营业执照");
        //默认营业执照
        objectMap.put("orgBusinessLicFile", orgBusinessLicFileURI);
        objectMap.put("orgBusinessLicFileName", elgResourceService.getFileNameAndType(orgBusinessLicFile.toPath()));


        return objectMap;
    }


    @PostMapping("/saveBidderApplyInfo")
    @Transactional(rollbackFor = Exception.class)
    public AcceptOrderInfoDO saveBidderApplyInfo(@RequestBody BidderApplyInfo bidderApplyInfo) {
        //出函机构
        GuaranteeInstitutionDO institutionDO = institutionService.getInstitutionByCode(bidderApplyInfo.getInstitutionCode());
        //担保机构
        OrganizationDO organizationDO = organizationService.getOrganizationByCode(bidderApplyInfo.getOrgCode());

        ProjectInfoDO projectInfoDO = projectInfoService.selectById(bidderApplyInfo.getId());
        projectInfoDO.setId(null);
        projectInfoDO.setOrgId(organizationDO.getId());
        projectInfoService.saveOrUpdateProjectInfo(projectInfoDO);

        Long centerId = projectInfoDO.getCenterId();
        Long orgId = organizationDO.getId();
        BidCustomerDO bidCustomerDO = BidCustomerDO.builder()
                .centerId(centerId).orgId(orgId)
                .bidderName(bidderApplyInfo.getBidderOrgName())
                //todo 页面暂没有默认
                .bidderCreditCode("88888888")
                .bidderContactName(bidderApplyInfo.getBidderContactName())
                .bidderContactTel(bidderApplyInfo.getBidderContactTel())
                .gmtCreate(Date.from(Instant.now())).build();
        bidCustomerService.saveOrUpdateBidCustomer(bidCustomerDO);

        String acceptOrderNo = IdGenerate.genAcceptOrderNo(CenterNoEnum.FUZHOU);
        //招标文件
        GuaranteeAttachmentInfoDO cur = new GuaranteeAttachmentInfoDO();
        cur.setId(IdGenerate.getId());
        cur.setOrgId(orgId);
        cur.setCenterId(centerId);
        cur.setAcceptOrderNo(acceptOrderNo);
        cur.setFileName(bidderApplyInfo.getTenderFileName());
        cur.setFileUrl(bidderApplyInfo.getTenderFileUrl());
        cur.setType(AttachmentFileType.TYPE_10.getType());
        Path tenderFilePath = elgResourceService.getFileByRelativePath(bidderApplyInfo.getTenderFile()).toPath();
        String fileType = elgResourceService.getFileType(tenderFilePath);
        String relativePath = elgResourceService.save2OfdPath(tenderFilePath, acceptOrderNo, bidderApplyInfo.getTenderFileName());
        String fileMd5 = elgResourceService.getFileMD5AsHex(elgResourceService.getAbsolutePath(relativePath));
        cur.setFilePath(relativePath);
        cur.setFileType(fileType);
        cur.setFileMd5(fileMd5);

        //招标文件
        GuaranteeAttachmentInfoDO cur1 = new GuaranteeAttachmentInfoDO();
        cur1.setId(IdGenerate.getId());
        cur1.setOrgId(orgId);
        cur1.setCenterId(centerId);
        cur1.setAcceptOrderNo(acceptOrderNo);
        cur1.setFileName(bidderApplyInfo.getOrgBusinessLicFileName());
        cur1.setFileUrl(bidderApplyInfo.getTenderFileUrl());
        cur1.setType(AttachmentFileType.TYPE_3.getType());
        Path orgBusinessLicFilePath = elgResourceService.getFileByRelativePath(bidderApplyInfo.getOrgBusinessLicFile()).toPath();
        String fileType1 = elgResourceService.getFileType(orgBusinessLicFilePath);
        String relativePath1 = elgResourceService.save2OfdPath(orgBusinessLicFilePath, acceptOrderNo, bidderApplyInfo.getOrgBusinessLicFileName());
        String fileMd51 = elgResourceService.getFileMD5AsHex(elgResourceService.getAbsolutePath(relativePath1));
        cur1.setFilePath(relativePath1);
        cur1.setFileType(fileType1);
        cur1.setFileMd5(fileMd51);


        guaranteeAttachmentInfoService.saveOrUpdateAttachmentInfoList(Lists.newArrayList(cur, cur1), acceptOrderNo);

        AcceptOrderInfoDO acceptOrderInfoDO = AcceptOrderInfoDO.builder()
                .centerId(centerId).orgId(orgId)
                .guaranteeNo(null)
                .centerOrderId(IdGenerate.getIdStr())
                .centerOrderTime(DateUtil.getDatetime())
                .acceptOrderNo(acceptOrderNo)
                .projectName(projectInfoDO.getProjectName())
                .sectionName(projectInfoDO.getSectionName())
                .bidCustomerName(bidCustomerDO.getBidderName())
                //当前投标期限==投递文件截止日期-出函机构处理开函天数
                .bidIndate(Date.from(projectInfoDO.getBidOpenTime().toInstant().minus(institutionDO.getOpenDays(), ChronoUnit.DAYS)))
                .guaranteeType(bidderApplyInfo.getGuaranteeType())//'保函类型'
                .guaranteeCategory(GuaranteeCategory.BID.getCategoryStr()) //'保函品种'
                .status(AcceptOrderStatus.WAIT_FIRST_TRAIL.getStatus())
                .projectId(projectInfoDO.getId())//  '投保项目主键id' 关联保存时统一设置
                .bidCustomerId(bidCustomerDO.getId())// '投保客户主键id'
                .institutionId(institutionDO.getId()) //???'开函机构主键' 怎么关联上
                .attachmentId(null)
                .warnFlag(0).warnContent(null)
                .gmtCreate(Date.from(Instant.now()))
                .userCreate(bidderApplyInfo.getBidderName())
                .build();

        acceptOrderInfoService.saveOrUpdateAcceptOrderInfo(acceptOrderInfoDO);

        return acceptOrderInfoDO;
    }

    @GetMapping("/resetStatus/{acceptOrderNo}")
    public Object reSetStatus(@PathVariable(value = "acceptOrderNo") String acceptOrderNo) {

        AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);
        if (acceptOrderInfo == null) {
            return "查无此受理订单记录:" + acceptOrderNo;
        }
        AcceptOrderInfoDO update = AcceptOrderInfoDO.builder().id(acceptOrderInfo.getId()).status(AcceptOrderStatus.WAIT_PAY_CONFIRM.getStatus()).build();
        acceptOrderInfoService.updateById(update);

        log.warn("受理订单号[{}]状态已经被重置为待支付状态", acceptOrderNo);
        return "受理订单:" + acceptOrderNo + ",重置待支付确认状态成功.保函编号为：" + acceptOrderInfo.getGuaranteeNo();
    }

    @GetMapping("getCustomerPayUrlInfo/{paramsB64}")
    public CustomerPayUrlInfo getCustomerPayUrlInfo(@PathVariable String paramsB64) {
        CustomerPayUrlInfo customerPayUrlInfo = new CustomerPayUrlInfo();
        try {
            JSONObject jsonpObject = JSON.parseObject(Base64.decodeStr(paramsB64));
            Long bidCustomerId = jsonpObject.getLong("bidCustomerId");
            String acceptOrderNo = jsonpObject.getString("acceptOrderNo");

            BidCustomerDO bidCustomer = bidCustomerService.selectById(bidCustomerId);
            Assert.notNull(bidCustomer, "查无此投保人信息");
            AcceptOrderInfoDO acceptOrderInfo = acceptOrderInfoService.getByAcceptOrderNo(acceptOrderNo);
            Assert.notNull(acceptOrderInfo, "查无此承保订单信息");
            AcceptOrderDetailVO acceptOrderDetail = acceptOrderInfoService.getAcceptOrderDetailById(acceptOrderInfo.getId());

//            Path receiveAmtPic = guaranteeAttachmentInfoService.getGuaAttPathNoAuth(acceptOrderNo, AttachmentFileType.TYPE_5);
//            if (receiveAmtPic != null) {
//                customerPayUrlInfo.setReceiveAmtPicBase64(Base64.encode(Files.readAllBytes(receiveAmtPic)));
//                customerPayUrlInfo.setReceiveAmtPic(elgResourceService.getRelativePath(receiveAmtPic));
//            }

//            Path openLicensePic = customerAttachmentService.getOpenLicensePicFile(bidCustomerId);
//            if (openLicensePic != null && Files.exists(openLicensePic)) {
//                customerPayUrlInfo.setAccountOpenLicensePicBase64(Base64.encode(Files.readAllBytes(openLicensePic)));
//                customerPayUrlInfo.setAccountOpenLicensePic(imageUploadConfig.getRegistImageUploadRelativePath(openLicensePic));
//                customerPayUrlInfo.setExistAccountOpenLicense("1");
//            }

            customerPayUrlInfo.setZtOpenBankName(ztAccountInfo.getOpenBankName());
            customerPayUrlInfo.setZtAccNo(ztAccountInfo.getAccNo());
            customerPayUrlInfo.setZtAccName(ztAccountInfo.getAccName());
            customerPayUrlInfo.setBidCustomer(bidCustomer);
            customerPayUrlInfo.setAcceptOrderDetail(acceptOrderDetail);

        } catch (Exception e) {
            throw new SystemRuntimeException(ErrorCode.INVALID, e, "参数错误" + e.getMessage());
        }
        return customerPayUrlInfo;
    }

}
